import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from tkinter import messagebox
from datetime import datetime
import requests
import math
import pandas as pd
import time
import ctypes

import json

y_gz_time = []
y_gz = []
y_gzf = []


def goto_email(file_path, title):
    smtp_server = "smtp.qq.com"
    smtp_port = 465
    sender_email = "929463988@qq.com"  # 替换为你的QQ邮箱
    password = r"ulbibkjhjkakbfgb"  # 替换为QQ邮箱的授权码（不是密码！）
    with open(file_path, 'r', encoding='utf-8') as file:
        file_content = file.read()
    message = MIMEMultipart()
    message['From'] = sender_email
    message['To'] = "929463988@qq.com"
    message['Subject'] = title
    message.attach(MIMEText(file_content, 'plain'))
    attachment = MIMEText(file_content)
    attachment.add_header('Content-Disposition', 'attachment', filename="file.txt")
    message.attach(attachment)
    try:
        with smtplib.SMTP_SSL(smtp_server, smtp_port) as server:
            server.login(sender_email, password)
            server.send_message(message)
    except smtplib.SMTPResponseException as e:
        if e.smtp_code == -1:  # 如果是 QQ 邮箱的奇怪响应
            pass
        else:
            messagebox.showinfo('提醒', f"SMTP 错误: {e}")
    except Exception as e:
        messagebox.showinfo('提醒', f"邮件发送失败: {e}")


jj_my = pd.read_excel(r'../Fund_form_files/JJ_bd.xlsx', dtype={'基金代码': str, '更新时间': str})
jj_rc = pd.read_excel(r'../Fund_form_files/JJ_all.xlsx', dtype={'基金代码': str, '基金名称': str, '板块': str})
jj_rd = pd.read_excel(r'../Fund_form_files/JJ_最近热点.xlsx', dtype={'基金代码': str, '基金名称': str, '板块': str})


def y_get_gz(fund_code):
    url = f"http://fundgz.1234567.com.cn/js/{fund_code}.js?rt={int(datetime.now().timestamp())}"
    headers = {'Referer': 'http://fund.eastmoney.com/', 'User-Agent': 'Mozilla/5.0'}
    response = requests.get(url, headers=headers, timeout=20)
    data = json.loads(response.text.replace("jsonpgz(", "").replace(");", ""))
    y_gz_time.append({data['gztime']})  # 保存获取的估值时间
    y_gz.append(float(data['gsz']))  # 保存获取的估值
    y_gzf.append(data['gszzl'])


def get_fund_data(fund_code, page_count=2):
    """获取基金历史净值和当日估值"""
    all_jz = []  # 存储历史净值
    all_dates = []  # 存储对应日期
    current_jz = 0.0  # 当日估值
    current_gzf = 0.0  # 当日估算涨幅
    # 获取历史净值数据
    for page in range(1, page_count + 1):  # 爬取一到page_count + 1页数据
        url = f"http://api.fund.eastmoney.com/f10/lsjz?fundCode={fund_code}&pageIndex={page}&pageSize=20"
        headers = {'Referer': 'http://fundf10.eastmoney.com', 'User-Agent': 'Mozilla/5.0'}
        try:
            r = requests.get(url, headers=headers, timeout=10)
            data = r.json()['Data']['LSJZList']
            # 按时间顺序插入数据（最新的在前面）倒序列表--
            for item in data:
                all_jz.insert(0, float(item['DWJZ']))
                all_dates.insert(0, item['FSRQ'])
        except Exception as e:
            print(f"基金 {fund_code} 历史数据获取失败: {e}")
            return None, None, 0
    try:  # 获取当日估值数据
        gz_url = f"http://fundgz.1234567.com.cn/js/{fund_code}.js"
        gz_response = requests.get(gz_url, timeout=10)
        gz_data = gz_response.text
        current_jz = float(gz_data.split('gsz":"')[1].split('","')[0])  # 从JS格式数据中提取估值
        current_gzf = float(gz_data.split('gszzl":"')[1].split('","')[0])  # 从JS格式数据中提取估涨幅
    except Exception as e:
        print(f"基金 {fund_code} 当日估值获取失败: {e}")
    return all_jz, all_dates, current_jz, current_gzf


def generate_trading_signal(current_price, lower_band, upper_band, ma20):
    if current_price <= lower_band * 1.02:
        return "强烈买入", "价格触及布林带下轨"
    elif current_price >= upper_band * 1.02:
        return "卖出止盈", "价格触及布林带上轨"
    elif current_price < ma20:
        return "观望", "价格在中轨下方"
    else:
        return "持有", "价格在中轨上方"


if __name__ == '__main__':
    result = ctypes.windll.user32.MessageBoxW(0, "你要运行倒计时吗？", "程序执行", 0x00000004)
    if result == 6:
        while 1:
            time.sleep(1)
            now_time = datetime.now().strftime('%H%M')
            print(f'倒计时还剩{1445 - int(now_time)}分钟')
            if now_time == '1445':
                break
    now_time = datetime.now().strftime('%m月%d日')
    jj_code = jj_my['基金代码'].values
    jj_name = jj_my['基金名称'].values
    jj_jun_ben = jj_my['平均成本'].values  # 持仓成本
    jj_cy_fe = jj_my['持有份额'].values
    jj_max_hc = jj_my['最大回撤'].values
    print('‍🐦‍🔥🐦‍🔥🐦‍🔥🐦‍🔥😎持有分析🐦‍🔥🐦‍🔥🐦‍🔥🐦‍🔥')
    with open(f'分析报告/{now_time}持仓分析报告', 'w', encoding='utf-8') as f:
        for i in range(len(jj_code)):
            print(f'🔍{jj_name[i]}')
            f.write(f'🔍{jj_name[i]}\n')
            jz_list, time_list, gz, gzf = get_fund_data(jj_code[i], 2)
            """计算布林带指标"""
            jz_list20 = jz_list[-20:]  # 取最新20条历史净值
            my_MA20 = sum(jz_list20) / 20  # 计算20日均线
            my_bz_c = math.sqrt(sum((x - my_MA20) ** 2 for x in jz_list20) / 20)  # 计算20日标准差(波动率)
            my_upper_band = my_MA20 + 2 * my_bz_c  # 布林带上轨 = 中轨 + 2倍标准差
            my_lower_band = my_MA20 - 2 * my_bz_c  # 布林带下轨 = 中轨 - 2倍标准差
            syl = ((gz - jj_jun_ben[i]) / jj_jun_ben[i]) * 100  # 基金收益率
            jl = (gz - my_upper_band) / my_upper_band * 100
            # ====================================================================
            print(f'💰平均成本: {jj_jun_ben[i]} | 估收益率: {syl:.2f}% | 最大回撤：{jj_max_hc[i]}%')
            print(f'💰当日估值: {gz:.4f} | 估算涨幅: {gzf:.2f}%')
            f.write(f'💰平均成本: {jj_jun_ben[i]}\n')
            f.write(f'💰估收益率: {syl:.2f}% | 比较回撤：{jj_max_hc[i] / 2:.2f}%\n')
            f.write(f'💰当日估值: {gz:.4f} | 估算涨幅: {gzf:.2f}%\n')
            if gz >= my_upper_band * 1.02 or syl >= 5:
                print(f'✅ 信号: 止盈')
                f.write(f'✅ 信号: 止盈|距离上轨{jl:.2f}%')
            elif gz <= my_lower_band and gzf < 0:  # 新加条件,当日必须下跌才买入 * 1.02
                print(f'✅ 信号: 半仓')
                f.write(f'✅ 信号: 半仓|距离上轨{jl:.2f}%')
            elif gz < my_MA20 and syl < -8:
                print(f'✅ 信号: 清仓止损')
                f.write(f'✅ 信号: 清仓止损|距离上轨{jl:.2f}%')
            else:
                print(f'✅ 信号: 继续持有|距离上轨{jl:.2f}%')
                f.write(f'✅ 信号: 继续持有|距离上轨{jl:.2f}%')
            print('-----------------------------------------')
            f.write(f'\n-----------------------------------------\n')
    print('🐉🐉🐉🐉🐉🐉🐉🐉🐉🐉🐉🐉🐉')
    print('‍🐦‍🔥🐦‍🔥🐦‍🔥🐦‍🔥🎢入场分析🐦‍🔥🐦‍🔥🐦‍🔥🐦‍🔥')
    with open(f'分析报告/{now_time}入场分析报告', 'w', encoding='utf-8') as f2:
        for j in range(len(jj_rc['基金代码'].values)):
            fund_code = jj_rc['基金代码'].values[j]
            fund_name = jj_rc['基金名称'].values[j]
            fund_type = jj_rc['板块'].values[j]
            if fund_code not in jj_my['基金代码'].values:
                print(f'🔍{fund_name} ({fund_code})--{fund_type}')
                try:
                    jz_list, date_list, current_value, gzf = get_fund_data(fund_code, 2)
                    recent_prices = jz_list[-20:]
                    recent_prices5 = jz_list[-5:]
                    rc_ma20 = sum(recent_prices) / 20  # 20日均值
                    rc_ma5 = sum(recent_prices5) / 5  # 20日均值
                    my_bz_c = math.sqrt(sum((x - rc_ma20) ** 2 for x in recent_prices) / 20)  # 标准
                    rc_upper_band = rc_ma20 + 2 * my_bz_c  # 布林上轨
                    rc_lower_band = rc_ma20 - 2 * my_bz_c  # 布林下轨
                    # 计算关键指标
                    # distance_to_upper_pct = ((rc_upper_band - current_value) / rc_upper_band) * 100
                    distance_to_lower_pct = ((current_value - rc_lower_band) / rc_lower_band) * 100
                    distance_to_ma20_pct = ((current_value - rc_ma20) / rc_ma20) * 100  # 距中轨%
                    # ====================================================================
                    print(f'💰当日估值: {current_value:.4f} | 估算涨幅: {gzf:.2f}%')
                    if current_value <= rc_lower_band and gzf < 0:  # 新加条件,当日必须下跌才买入
                        print(f'✅ 信号: 半仓|距离下轨{distance_to_lower_pct:.2f}%')
                        f2.write(f'🔍{fund_name} ({fund_code})\n')
                        f2.write(f'🍞板块：{fund_type}\n')
                        f2.write(f'💰当日估值: {current_value:.4f} | 估算涨幅: {gzf:.2f}%\n')
                        f2.write(f'✅ 信号: 半仓 | 距离下轨{distance_to_lower_pct:.2f}%\n')
                        f2.write(f'-----------------------------------------\n')
                    else:
                        print(f'✅ 信号: 观望')
                    print('-----------------------------------------')
                except Exception as e:
                    print('出错了', e)
    print('🐉🐉🐉🐉🐉🐉🐉🐉🐉🐉🐉🐉🐉')
    print('‍🐦‍🔥🐦‍🔥🐦‍🔥🐦‍🔥♨️热点分析🐦‍🔥🐦‍🔥🐦‍🔥🐦‍🔥')
    with open(f'分析报告/{now_time}热点分析', 'w', encoding='utf-8') as f3:
        for j in range(len(jj_rd['基金代码'].values)):
            fund_code = jj_rd['基金代码'].values[j]
            fund_name = jj_rd['基金名称'].values[j]
            fund_type = jj_rd['板块'].values[j]
            if fund_code not in jj_my['基金代码'].values:
                print(f'🔍{fund_name} ({fund_code})--{fund_type}')
                try:
                    ux = ''
                    two_x = ''
                    lx = ''
                    jz_list, date_list, current_value, gzf = get_fund_data(fund_code, 2)
                    recent_prices = jz_list[-20:]
                    recent_prices5 = jz_list[-5:]
                    rc_ma5 = sum(recent_prices5) / 5  # 5日均值
                    rc_ma20 = sum(recent_prices) / 20  # 20日均值
                    my_bz_c = math.sqrt(sum((x - rc_ma20) ** 2 for x in recent_prices) / 20)  # 标准
                    rc_upper_band = rc_ma20 + 2 * my_bz_c  # 布林上轨
                    rc_lower_band = rc_ma20 - 2 * my_bz_c  # 布林下轨
                    distance_to_upper_pct = ((current_value - rc_upper_band) / rc_upper_band) * 100  # 距上轨%
                    distance_to_ma20_pct = ((current_value - rc_ma20) / rc_ma20) * 100  # 距中轨%
                    distance_to_lower_pct = ((current_value - rc_lower_band) / rc_lower_band) * 100  # 距下轨%
                    # ====================================================================
                    if distance_to_upper_pct > 0:
                        ux = '上方'
                    else:
                        ux = '下方'
                    if distance_to_ma20_pct > 0:
                        two_x = '上方'
                    else:
                        two_x = '下方'
                    if distance_to_lower_pct > 0:
                        lx = '上方'
                    else:
                        lx = '下方'
                    print(f'💰当日估值: {current_value:.4f} | 估算涨幅: {gzf:.2f}%')
                    print(f'💰MA20: {rc_ma20:.4f} | MA5: {rc_ma5:.4f}')
                    print(f'💰距离上轨: {distance_to_upper_pct:.2f}%  {ux}')
                    print(f'💰距离中轨: {distance_to_ma20_pct:.2f}%  {two_x}')
                    print(f'💰距离下轨: {distance_to_lower_pct:.2f}%  {lx}')
                    print('-----------------------------------------')
                    f3.write(f'🔍{fund_name}({fund_code})\n')
                    f3.write(f'🍞{fund_type}\n')
                    f3.write(f'💰当日估值: {current_value:.4f} | 估算涨幅: {gzf:.2f}%\n')
                    f3.write(f'💰MA20: {rc_ma20:.4f} | MA5: {rc_ma5:.4f}\n')
                    f3.write(f'💰距离上轨: {distance_to_upper_pct:.2f}%  {ux}\n')
                    f3.write(f'💰距离中轨: {distance_to_ma20_pct:.2f}%  {two_x}\n')
                    f3.write(f'💰距离下轨: {distance_to_lower_pct:.2f}%  {lx}\n')
                    f3.write('-----------------------------------------\n')
                except Exception as ee:
                    print(f'错误:{ee}')
    y_get_gz('023948')
    jj_y = pd.read_excel('../Fund_form_files/Y策略验证基金.xlsx')
    y_jj_jz = jj_y['买入净值'].values
    y_jj_fe = jj_y['买入份额'].values
    min_shop_dj = y_jj_jz[len(y_jj_jz) - 1]
    jl = (y_gz[0] - min_shop_dj) / min_shop_dj * 100
    with open(f'分析报告/{now_time}Y策略判断报告', 'w', encoding='utf-8') as f2:
        f2.write('🏆银华品质消费股票C(023948)\n')
        f2.write(f'🛒最小净值:{min_shop_dj}\n🛒当日估值:{y_gz[0]}\n')
        f2.write(f'📈策略涨幅:{jl:.2f}%\n')
        if jl >= 1:
            print(f'可卖出{y_jj_fe[len(y_jj_jz) - 1]}份基金')
            f2.write(f'🧐卖出{y_jj_fe[len(y_jj_jz) - 1]}份')
        elif jl <= -1:
            print('买')
            f2.write(f'🧐买一下')
        else:
            print('今天不动')
            f2.write('🧐没有明显信号')
    goto_email(f'分析报告/{now_time}热点分析', '热点分析')
    goto_email(f'分析报告/{now_time}入场分析报告', '入场分析报告')
    goto_email(f'分析报告/{now_time}持仓分析报告', '持仓分析报告')
    goto_email(f'分析报告/{now_time}Y策略判断报告', 'Y策略今日操作')
